(function($) {  
    /**
     * 默认配置.
     */  
    var _defaultConfig = {
        editable : false,
        isSelectText : false, //是否以text值作为下拉框的值.
        mapping : {
            text : 'text',
            value : 'value'
        }
    };	
	/**
	 * 重新组织SelectBox的HTML模板.
	 */
	var _selectBoxTmp = [
		'<div class="selectBox">', 
			'<div class="trigger formField"  id="<%= id %>"></div>', 
			'<ul class="items" style="display:none;">', 
				'<%= lis %>', 
			'</ul>',
		'</div>'
	].join('');

	//---------------------------------------------------------------------------------------------
	
	/**
     * @description : SelectBox
     */
	function SelectBox(selector, config){
		var _this = this, 
            $selectBox = $(selector);
		
		this.config = $.extend(true, {}, _defaultConfig, config);
		
		if($selectBox.hasClass('editable')){
			this.config['editable'] = true;
		}
		if(this.config['editable']){
		    this.config['isSelectText'] = true;
		}		
		//包装器.	
		this.$wrapper = $(tmpl(_selectBoxTmp, {
	        id : this.config['id'] || $selectBox.attr('id'),
	        lis : $selectBox.html()		        
	    }));		
        this.$trigger = this.$wrapper.find('>.trigger');        
        this.$ddList = this.$wrapper.find('>.items');        
        //外观.		
		this.$wrapper.addClass(this.config['theme']);
        this.$wrapper.style(this.config['style']);           
		if(this.config['width']){
		    this.$wrapper.css('min-width', this.config['width']);
		}
		
		//可编辑逻辑.
		if(_this.config['editable']){
			_this.$trigger.attr('contenteditable', true).addClass('inputbox').bind({
			    keydown : function(e){
			        var keyword = $(this).text().trim().toLowerCase();
			        var $items = _this.$ddList.find('li:visible'),
			            $currentItem = $items.filter('.current');
			            
			        if( e.keyCode === 13 ){			            
                        if( $currentItem.size() ){                            
                            _this.setValue( $currentItem.attr('val') );                            
                        } 
			            return false;
			        } else if( e.keyCode === 37 || e.keyCode === 38 ){   //left or up		                 
		                 var $prevItem = $currentItem.prevAll(':visible').first();		                     		                     
	                     $prevItem = !!$prevItem.size() ? $prevItem : $items.last(':visible');
		                 $prevItem.addExclusiveClass('current');		                 
			        } else if( e.keyCode === 39 || e.keyCode === 40 ){   //right or down			                                      
                         var $nextItem = $currentItem.nextAll(':visible').first();                          
                         $nextItem = !!$nextItem.size() ? $nextItem : $items.first(':visible');                               
                         $nextItem.addExclusiveClass('current');
			        }
			    }, 
			    'keyup click focus' : function(e){  
			        var keyword = $(this).text().trim().toLowerCase();
			        if(keyword.indexOf('...') > -1){
			            keyword = '';
			        }
			        _this.$ddList.find('li').each(function(){
			            var itemText = $(this).text().trim().toLowerCase();			             
			            if( e.type === 'click' || e.type === 'focus' || !keyword || itemText.indexOf( keyword ) > -1){
			                $(this).show();
			            } else {
			                $(this).hide();
			            }
			        });
			        e.stopPropagation();
			    }
			});
		}
					
		//load ajax data.
		if( _this.config['data'] ){
		    if(Type.isArray(_this.config['data'])){
                _this.refresh(_this.config['data']);    
		    } else {
    			var dataCfg = _this.config['data'];			
    			$.ajax({
    				type : dataCfg['type'],			
    				url : dataCfg['url'] || 'GET' 
    			}).done(ujs.hr(function(msg){
                    msg = JSON.insure(msg);                 
                    var ddListItems = JSON.getByPath(msg,dataCfg['root']);                 
                    
                    if(dataCfg['mapping']){
                        _this.config['mapping'] = dataCfg['mapping'];
                    }
                    _this.refresh(ddListItems);
                }));
			}
		}

		//修饰ddListItems.
		var $ddListItems = $( '>li', _this.$ddList );
		for(var i = 0, len = $ddListItems.length; i < len; i++) {
			var $ddListItem = $($ddListItems[i]);
			$ddListItem.attr('index', i);
			if(i == 0) {
			    if(Type.isUndefined(_this.config['value'])){		
				    _this.setValue($ddListItem.attr('val'), false);
				}
				$ddListItem.addClass('first');
			} else if(i == len - 1) {
				$ddListItem.addClass('last');
			}			
		}
		
		//选中菜单项时.		
		_this.$ddList.delegate('li','click', function(e){
		    var value = $(this).attr('val');		    	
			_this.setValue( Type.isUndefined(value) ? $(this).text().trim() : value );			
			e.stopPropagation();
		});

		/**
		 * trigger点击事件.
		 */
		_this.$trigger.bind( 
		    _this.config['triggerType'] === 'mouseover' ? 'mouseover click' : 'click', 
		    function(e) {		    
    			var triggerTemp = $(this);
    		    _this.$ddList[ e.type === 'mouseover' ? 'show' : 'toggle' ]('fast', function() {
    				triggerTemp.toggleClass('expand');
    			});			
    			//若trigger可编辑且内部文本为提示符时.
    			if(_this.config['editable'] && _this.$trigger.text().trim().endsWith('...')){
    				_this.$trigger.text('');
    			}
    			e.stopPropagation();
    		}
		);		
		//点击页面其它地方时，隐藏菜单.
		$(window).bind( 'click', function(e) {
			if(_this.$wrapper){			    
				if(_this.config['editable'] && _this.getSelectedIndex()){
					_this.setValue(_this.$trigger.text().trim());	
				}
				_this.hideDDList();		
			}
		});		
		//非ajax请求时，若设置了默认值.
		if( !_this.config['data'] ){
            if( _this.config['value'] ){             
                _this.setValue(_this.config['value'], false);
            }
		}		
		$selectBox.replaceWith( _this.$wrapper );
	}
	SelectBox.prototype.getValue = function(){	    
		return $.trim( !this.config['isSelectText'] ? this.$trigger.attr('selectedvalue') : this.$trigger.text() );
	};
	SelectBox.prototype.getSelectedIndex = function(){
	    return parseInt( this.$trigger.attr('selectedindex') ) || 0;
	};
	SelectBox.prototype.getSelectedItemText = function(){
		return this.$trigger.text().trim();
	};
	SelectBox.prototype.show = function(){
	    this.$wrapper.show();
	};
	SelectBox.prototype.hide = function(){
        this.$wrapper.hide();
    };
	SelectBox.prototype.setValue = function(val, isTriggerOnChange){	    	
		if( this.getValue() != val || new Boolean(this.config['enableClick'] ) ) {
			var selectedItem;						
			val = String(val);
			try {
			    //按value查找匹配项.			    
				selectedItem = $('.items>li[val="{0}"]'.format(
				    //转义jquery selector中的特殊字符 ,如 " : . / $ [ ]  @ "等.
				    val.replace( /\.|\:|\/|\$|\[|\]|\@/gi, function(chr){
				        return '\\' + chr;
				    })),
				    this.$wrapper
			    );
				if( !selectedItem.size() ){
				    //按text查找匹配项.
				    $('.items>li:contains("{0}")'.format(val), this.$wrapper).each(function(){
				        if($(this).text().trim() == val.trim()){
				            selectedItem = $(this);        
				        }
				    });					
					if(selectedItem.size() && selectedItem.attr('val')){
					    val = selectedItem.attr('val');
					} else {
					    //实在未找到匹配项，则选中第一项。
					    selectedItem = $('.items>li:first');
					}
				}
				this.selectedItem = selectedItem;
			 } catch(e){}
						
			if( selectedItem && selectedItem.size() ){			    
				this.$trigger
					.attr('selectedvalue', val)
					.attr('selectedindex', selectedItem.attr('index'))
					.text(selectedItem.text().trim());
				selectedItem.siblings().removeClass('current');
				selectedItem.addClass('current');
				if(this.config['onchange'] && isTriggerOnChange !== false) {
					this.config['onchange'](val, selectedItem.attr('index'), selectedItem[0]);
				}
			} else {
				var newText = this.$trigger.text().trim();
				this.$trigger
					.attr('selectedvalue', newText)
					.attr('selectedindex', -1);					
				if(this.config['onchange'] && isTriggerOnChange !== false) {
					this.config['onchange'](newText, -1);
				}
			}
		}
		if(isTriggerOnChange !== false){
		    this.hideDDList();       
		}
		return this;
	};
	
	SelectBox.prototype.refresh = function(data){               
        var _this = this,
            textFieldName = _this.config['mapping']['text'],
            valueFieldName = _this.config['mapping']['value'],
            alternatetextFiledName = _this.config['mapping']['alternatetext'];
        
        data = JSON.parse(JSON.stringify(data));  //data参数值为引用传递, 此处需要修改data，为避免影响客户代码，深copy一份。  
        if(_this.config['initData']){
            data.unshift(_this.config['initData']);
        }
            
        _this.$ddList.html('');
        for(var i=0, len = data.length ; i < len; i++ ){            
            _this.$ddList.append( '<li val="{value}" index="{index}" title="{text}" >{text}</li>'.format({
                index : i + 1,
                value : Type.isUndefined(data[i][valueFieldName]) ? data[i][textFieldName] : data[i][valueFieldName],                
                text : data[i][textFieldName] || data[i][alternatetextFiledName]
            }));
        }
        
        if( !Type.isUndefined(_this.config['value']) ){
            _this.setValue(_this.config['value'], false);
        }    
	};
	
	//隐藏菜单.
	SelectBox.prototype.hideDDList = function(){
        this.$ddList.hide();
        this.$trigger.removeClass('expand');
    };
    
    SelectBox.prototype.hideDDListIfNecessary = function(){
        var $visibleItems = this.$ddList.find('li:visible');
        if(!$visibleItems.length){
            this.$ddList.hide();
            this.$trigger.removeClass('expand');
        }
    };
    
    SelectBox.prototype.showDDList = function(){
        this.$ddList.show();
        this.$trigger.addClass('expand');
    };
	
	//---------------------------------------------------------------------------------------------

	//注册为jQuery插件.
	$.fn.selectBox = function(config) {	  	      	    
		var selectBoxObjArr = this.map(function() {		    
			var selectBoxConfig = $(this).extractConfig(config);				
			if(selectBoxConfig['value'] && !(config && config['value'])) {			    
			    selectBoxConfig['value'] = selectBoxConfig['value'].evaluate();				
			}			
			if(selectBoxConfig['data']){
			    if(selectBoxConfig['data']['url']){
    				var ajaxUrl = selectBoxConfig['data']['url'];					
    				if(ajaxUrl.indexOf('"') < 0 && ajaxUrl.indexOf("'") < 0 ){
    					ajaxUrl = '"{0}"'.format(ajaxUrl);
    				}	
    				selectBoxConfig['data']['url'] = eval('(' + ajaxUrl + ')');
				}
			}			
			if(selectBoxConfig['onchange'] && Type.isString(selectBoxConfig['onchange'])){
				selectBoxConfig['onchange'] = selectBoxConfig['onchange'].evaluate();
			}			
			var selectBoxObj = new SelectBox(this, selectBoxConfig);			
			selectBoxObj.$wrapper.data('selectBox', selectBoxObj).data('formField', selectBoxObj);

			return selectBoxObj;
		}).get();
		
		return selectBoxObjArr.length > 1 ? selectBoxObjArr : selectBoxObjArr[0];
	};
	
    //-----------------------------------------------------------------------------
    
    $(function(){
        //自动加载下拉框绑定的值.
        $('.selectBox.auto').selectBox();
    });
    	
})($);